package customProxy

import (
	"fmt"
	"golang.org/x/net/context"
	"golang.org/x/net/proxy"
	"io"
	"net"
	"net/http"
	"time"
)

type ProxyType string

const (
	Http  ProxyType = "http"
	SOCKS ProxyType = "socks"
)

type ProxyServer string

const (
	IPID ProxyServer = "643cfb36cf37ef59.fjt.as.ipidea.online:2333"
	RO   ProxyServer = "gate9.rola.info:2029"
)

type Proxy struct {
	Type     string
	Server   string
	Username string
	Password string
}

var (
	IPIDSocks = Proxy{
		Type:     "socks",
		Server:   "643cfb36cf37ef59.fjt.as.ipidea.online:2333",
		Username: "ipideacsnew-zone-custom-region-%s-session-%s-sessTime-120",
		Password: "209209usidea",
	}
	ROSocks = Proxy{
		Type:     "socks",
		Server:   "gate9.rola.info:2029",
		Username: "drycsroip_%s-country-%s",
		Password: "209209usroip",
	}
	IPIDHttp = Proxy{
		Type:     "http",
		Server:   "643cfb36cf37ef59.fjt.as.ipidea.online:2333",
		Username: "ipideacsnew-zone-custom-region-%s-session-%s-sessTime-120",
		Password: "209209usidea",
	}
	ROHttp = Proxy{
		Type:     "http",
		Server:   "gate9.rola.info:2029",
		Username: "drycsroip_%s-country-%s",
		Password: "209209usroip",
	}
)

func (p Proxy) CreateClient(region, randomInfo string) (*http.Client, error) {
	var user = fmt.Sprintf(p.Username, region, randomInfo)
	if p == ROSocks || p == ROHttp {
		user = fmt.Sprintf(p.Username, randomInfo, region)
	}
	// 创建带认证信息的 SOCKS5 Dialer
	auth := &proxy.Auth{
		User:     user,
		Password: p.Password,
	}

	dialer, err := proxy.SOCKS5("tcp", p.Server, auth, proxy.Direct)
	if err != nil {
		return nil, fmt.Errorf("failed to create SOCKS5 dialer: %v", err)
	}

	// 自定义 Transport 使用该 Dialer
	transport := &http.Transport{
		DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
			return dialer.Dial(network, addr)
		},
	}

	return &http.Client{
		Transport: transport,
		Timeout:   10 * time.Second,
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse // 禁止自动重定向
		},
	}, err
}

func Req(client *http.Client, request *http.Request) (string, error) {
	resp, err := client.Do(request)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	// 如果是重定向
	if resp.StatusCode >= 300 && resp.StatusCode <= 399 {
		location := resp.Header.Get("Location")
		if location == "" {
			return "", fmt.Errorf("redirect with no Location header")
		}
		fmt.Println("Found redirect, following:", location)
		return Req(client, CreateRequest(location, request.Header.Get("User-Agent"))) // 手动跟随跳转
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	return string(body), nil
}
func CreateRequest(url string, ua string) *http.Request {
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("User-Agent", ua)
	return req
}
